home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C++
/
Frameworks
/
Sprocket Framework DR2
/
Sprocket Framework
/
AEThreads.cp
< prev
next >
Wrap
Text File
|
1996-06-15
|
5KB
|
202 lines
/*
File: AEThreads.cp
Project: Sprocket Framework 1.1 (DR2), released 6/15/96
Contains: Routines for installing threaded AppleEvent handlers
To Do: To really support AppleScript™, we’ll need to do ALOT more work in here.
Sprocket Major Contributors:
----------------------------
Dave Falkenburg, producer of Sprocket 1.0
Bill Hayden, producer of Sprocket 1.1
Steve Sisak, producer of the upcoming Sprocket 2.0
Pete Alexander Steve Falkenburg Randy Thelen
Eric Berdahl Nitin Ganatra Chris K. Thomas
Marshall Clow Dave Hershey Leonard Rosenthal
Tim Craycroft Dave Mark Dean Yu
David denBoer Gary Powell
Cameron Esfahani Jon Summers Apple Computer, Inc.
Comments, Additions, or Corrections:
------------------------------------
Bill Hayden, Nikol Software <nikol@codewell.com>
*/
#ifndef __AETHREADS__
#include "AEThreads.h"
#endif
#ifndef __ERRORS__
#include <Errors.h>
#endif
#ifndef __APPLEEVENTS__
#include <AppleEvents.h>
#endif
#include "ThreadContext.h"
#include "SprocketMacros.h"
pascal OSErr SpawnAEThread(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon);
class AEThreadContext : public TThreadContext
{
protected:
AEEventHandlerUPP fHandler; // The real handler
const AppleEvent* fEvent;
AppleEvent* fReply;
long fRefcon;
public:
AEThreadContext(AEEventHandlerUPP handler, const AppleEvent* event, AppleEvent* reply, long refcon) : fHandler(handler), fEvent(event), fReply(reply), fRefcon(refcon) {};
virtual ~AEThreadContext() {};
static pascal void* AEThreadProc(AEThreadContext* context);
friend pascal OSErr SpawnAEThread(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon);
};
struct AEThreadDesc // Kept in the OS refcon
{
AEEventHandlerUPP handler; // The real handler
long refcon; // The real refcon
Size stackSize; // Stack size for handling event
ThreadOptions options; // Thread options for event
ThreadID holder; // used as a semaphore
};
AEEventHandlerUPP gSpawnAEThreadUPP = nil;
/*****************************************************************************/
pascal OSErr AEInstallThreadedEventHandler( AEEventClass theAEEventClass,
AEEventID theAEEventID,
AEEventHandlerUPP proc,
long handlerRefcon,
ThreadOptions options,
Size stacksize)
{
AEThreadDesc* desc = (AEThreadDesc*) NewPtr(sizeof(AEThreadDesc));
OSErr err = MemError();
if (gSpawnAEThreadUPP == nil)
{
gSpawnAEThreadUPP = NewAEEventHandlerProc(SpawnAEThread);
}
if (err == noErr)
{
desc->handler = proc;
desc->refcon = handlerRefcon;
desc->stackSize = stacksize;
desc->options = options;
desc->holder = kNoThreadID;
err = AEInstallEventHandler(theAEEventClass, theAEEventID, gSpawnAEThreadUPP, (long) desc, false);
}
return err;
}
/*****************************************************************************/
pascal void* AEThreadContext::AEThreadProc(AEThreadContext* context)
{
OSErr result = noErr;
try
{
result = CallAEEventHandlerProc(context->fHandler, context->fEvent, context->fReply, context->fRefcon);
// Since the event was suspended, we need to stuff the error code ourselves
// note that there's not much we can do about reporting errors beyond here
}
catch(OSErr err)
{
result = err;
}
OSErr err;
err = AEPutAttributePtr(context->fReply, keyErrorNumber, typeShortInteger, &result, sizeof(result));
if (err)
DebugMessage("\pAEPutAttributePtr failed installing error code - very bad");
err = AEResumeTheCurrentEvent(context->fEvent, context->fReply, kAENoDispatch, 0); // This had better work
if (err)
DebugMessage("\pAEResumeTheCurrentEvent failed - very bad");
delete context;
return nil;
}
/*****************************************************************************/
pascal OSErr AEHandleInThread( const AppleEvent* event,
AppleEvent* reply,
AEEventHandlerUPP handler,
long handlerRefcon,
ThreadOptions options,
Size stacksize)
{
OSErr result;
AEThreadContext* context = new AEThreadContext(handler, event, reply, handlerRefcon);
try
{
if (!context)
throw(nilHandleErr);
context->CreateThread(kCooperativeThread, (ThreadEntryProcPtr) AEThreadContext::AEThreadProc, stacksize, options);
result = AESuspendTheCurrentEvent(event);
}
catch(OSErr err)
{
delete context;
result = err;
}
return result;
}
/*****************************************************************************/
pascal OSErr SpawnAEThread(const AppleEvent *event, AppleEvent *reply, long handlerRefcon)
{
AEThreadDesc* desc = (AEThreadDesc*) handlerRefcon;
return AEHandleInThread(event, reply,
desc->handler,
desc->refcon,
desc->options,
desc->stackSize);
}